﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "QtLineEdit.h"
#include "GbmpNew.h"
#include "LineEditEvent.h"
#include "LineEditEventArgs.h"
#include "ControlDefinitionChangeEvent.h"
#include "LineEditDefinition.h"
#include "LineEditDefinitionReference.h"
#include "UiQtUtil.h"
#include <QCoreApplication>
#include "ValidatorBase.h"
#include "BalloonTipManager.h"
#include "ControlDefinitionUtil.h"
#include "NumberValidator.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

gcmp::QtLineEdit::QtLineEdit(OwnerPtr<ILineEditDefinition> pControlDefinition, QWidget* pParent/* = nullptr*/)
    : m_pControlDefinition(TransferOwnership(pControlDefinition))
    , QLineEdit(pParent)
{
    if (!m_pControlDefinition)
    {
        DBG_WARN(L"m_pControlDefinition为空",L"GDMPLab",L"2024-03-30");
        return;
    }

    if (m_pControlDefinition->GetValidator() == nullptr)
    {
        if (m_pControlDefinition->GetInputType() == LineEditInputType::InputDouble)
        {
            OwnerPtr<NumberValidator<double>> pValidator = NEW_AS_OWNER_PTR(NumberValidator<double>);
            if (pValidator != nullptr)
            {
                const LineEditDefinition *pLineEditDefinition = dynamic_cast<LineEditDefinition*>(m_pControlDefinition.get());
                const LineEditDefinitionReference *pLineEditDefinitionReference = dynamic_cast<LineEditDefinitionReference*>(m_pControlDefinition.get());
                if (!pLineEditDefinition)
                {
                    pLineEditDefinition = pLineEditDefinitionReference->GetLineEditDefinition();
                }
                DBG_WARN_AND_RETURN_VOID_UNLESS(pLineEditDefinition, L"LineEditDefinition不能为空",L"GDMPLab",L"2024-03-30");
                pValidator->SetDecimals(pLineEditDefinition->GetDecimals());
                m_pControlDefinition->SetValidator(TransferOwnership(pValidator));
            }
        }
        else if (m_pControlDefinition->GetInputType() == LineEditInputType::InputInt)
        {
            OwnerPtr<NumberValidator<int>> pValidator = NEW_AS_OWNER_PTR(NumberValidator<int>);
            if (pValidator != nullptr)
            {
                m_pControlDefinition->SetValidator(TransferOwnership(pValidator));
            }
        }
    }

    bool visible = m_pControlDefinition->IsVisible();
    bool enabled = m_pControlDefinition->IsEnabled();
    this->setText(QString::fromStdWString(m_pControlDefinition->GetText()));
    setVisible(visible);
    setEnabled(enabled);
    
    QObject::connect(this, &QLineEdit::textEdited, this, &QtLineEdit::OnTextEdited);
    QObject::connect(this, &QLineEdit::editingFinished, this, &QtLineEdit::OnEditingFinished);
    QObject::connect(this, &QLineEdit::textChanged, this, &QtLineEdit::OnTextChanged);
    QObject::connect(this, &QLineEdit::selectionChanged, this, &QtLineEdit::OnTextSelectChanged);

    setObjectName(QString::fromStdWString(m_pControlDefinition->GetId()));
    setProperty(IS_DEFINITION, true);

    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Add(this);
    }

    int e = (int)this->echoMode();
}

gcmp::QtLineEdit::~QtLineEdit()
{
    IControlDefinitionChangeEvent* pControlDefinitionChangeEvent = ControlDefinitionUtil::GetControlDefinitionChangeEvent(m_pControlDefinition.get());
    if (pControlDefinitionChangeEvent)
    {
        pControlDefinitionChangeEvent->Delete(this);
    }
}

void gcmp::QtLineEdit::SetText(const std::wstring& text)
{   
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    setText(QString::fromStdWString(text));
    if (m_pControlDefinition->GetText() != text)
    {
        m_pControlDefinition->SetText(text);
    }
}


void gcmp::QtLineEdit::SelectAll()
{
    this->selectAll();
}

void gcmp::QtLineEdit::Clear()
{
    this->clear();
    if (m_pControlDefinition->GetText() != L"")
    {
        m_pControlDefinition->Clear();
    }
}

void QtLineEdit::SetValidator(OwnerPtr<ValidatorBase> pValidator)
{
    m_validator = TransferOwnership(pValidator);
}

const ValidatorBase* QtLineEdit::GetValidator() const
{
    return m_validator.get();
}


void gcmp::QtLineEdit::On(IControlDefinitionChangeEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    if (pArgs->GetType() == ControlDefinitionChangeEventType::Other)
    {
        if (text().toStdWString() != m_pControlDefinition->GetText())
        {
            setText(QString::fromStdWString(m_pControlDefinition->GetText()));
        }
        /////////////下面是设置可见性及可用性///////////////////////////
        bool visible = m_pControlDefinition->IsVisible();
        if (isVisible() != visible)
        {
            setVisible(visible);
        }
        bool enabled = m_pControlDefinition->IsEnabled();
        if (isEnabled() != enabled)
        {
            setEnabled(enabled);
        }
        //////////////////////////////////////////////////////////////
        std::wstring selectedText = this->selectedText().toStdWString();
        int selectionStart = this->selectionStart();

        int selectionStartDefine = GetDefinitionSelectionStart();
        std::wstring selectedTextDefine = m_pControlDefinition->GetSelectedText();
        if (selectedTextDefine != selectedText || selectionStartDefine != selectionStart)
        {
            if (selectedTextDefine == L"" && selectionStartDefine == -1)
            {
                this->deselect();
                return;
            }
            this->setSelection(selectionStartDefine, (int)selectedTextDefine.length());
        }

    }

}

gcmp::IControlDefinition* gcmp::QtLineEdit::GetControlDefinition() const
{
    return const_cast<ILineEditDefinition*>(m_pControlDefinition.get());
}

void gcmp::QtLineEdit::UpdateStatus()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");

    setVisible(m_pControlDefinition->IsVisible());
    setEnabled(m_pControlDefinition->IsEnabled());
}

void gcmp::QtLineEdit::OnTextEdited(const QString & text)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    LineEditTextChangeFlag flag(true); 
    ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());
    if (m_pControlDefinition->GetText() != text.toStdWString())
    {
        m_pControlDefinition->SetText(text.toStdWString());
    }
    SetDefinitionIsEditing(true);
}

void gcmp::QtLineEdit::OnEditingFinished()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    
    ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());
    SetDefinitionIsEditing(false);
    LineEditEvent* ctrlEvent = dynamic_cast<LineEditEvent*>(m_pControlDefinition->GetEvent());
    if (ctrlEvent)
    {
        LineEditEventArgs args(LineEditEventType::EditingFinished, m_pControlDefinition->GetId(), text().toStdWString());
        ctrlEvent->Emit(&args);
    }
}

void gcmp::QtLineEdit::OnTextChanged(const QString & text)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    std::wstring textStr = text.toStdWString();
    if (m_pControlDefinition->GetText() != textStr)
    {
        ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());
        m_pControlDefinition->SetText(textStr);
    }
}

void gcmp::QtLineEdit::OnTextSelectChanged()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    int selectionStart = this->selectionStart();
    std::wstring selectText = this->selectedText().toStdWString();

    int selectionStartDefine = GetDefinitionSelectionStart();
    std::wstring selectedTextDefine = m_pControlDefinition->GetSelectedText();
    if (selectedTextDefine != selectText || selectionStartDefine != selectionStart)
    {
        ControlDefinitionChangeByUser changeByUser(m_pControlDefinition->GetId());
        SetDefinitionSelection(selectionStart, (int)selectText.length());
    }
    
}

int gcmp::QtLineEdit::GetDefinitionSelectionStart()
{
    DBG_WARN_AND_RETURN_UNLESS(m_pControlDefinition, -1, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    if (LineEditDefinition* pLineEditDefine = dynamic_cast<LineEditDefinition*>(m_pControlDefinition.get()))
    {
        return pLineEditDefine->GetSelectionStart();
    }
    else if (LineEditDefinitionReference* pLineEditDefineRef = dynamic_cast<LineEditDefinitionReference*>(m_pControlDefinition.get()))
    {
        return pLineEditDefineRef->GetSelectionStart();
    }
    else
    {
        DBG_WARN(L"类型不正确",L"GDMPLab",L"2024-03-30");
    }
    return -1;
}

bool gcmp::QtLineEdit::SetDefinitionSelection(int start, int length)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    if (LineEditDefinition* pLineEditDefine = dynamic_cast<LineEditDefinition*>(m_pControlDefinition.get()))
    {
        pLineEditDefine->SetSelection(start, length);
        return true;
    }
    else if (LineEditDefinitionReference* pLineEditDefineRef = dynamic_cast<LineEditDefinitionReference*>(m_pControlDefinition.get()))
    {
        pLineEditDefineRef->SetSelection(start, length);
        return true;
    }
    else
    {
        DBG_WARN(L"类型不正确",L"GDMPLab",L"2024-03-30");
    }
    return false;
}

bool gcmp::QtLineEdit::SetDefinitionIsEditing(bool isEditing)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_pControlDefinition, L"pControlDefinition为空",L"GDMPLab",L"2024-03-30");
    if (LineEditDefinition* pLineEditDefine = dynamic_cast<LineEditDefinition*>(m_pControlDefinition.get()))
    {
        pLineEditDefine->SetIsEditing(isEditing);
        return true;
    }
    else if (LineEditDefinitionReference* pLineEditDefineRef = dynamic_cast<LineEditDefinitionReference*>(m_pControlDefinition.get()))
    {
        pLineEditDefineRef->SetIsEditing(isEditing);
        return true;
    }
    else
    {
        DBG_WARN(L"类型不正确",L"GDMPLab",L"2024-03-30");
    }
    return false;
}
